/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Server;

import Client.Message;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 *Clase Servidor de correo.
 * se encarga de realizar el procesamiento de los correos enviados por los clientes.
 * @author Devys
 */
public class MailServer implements Serializable{

    private ListaMensajes Mensajes;
    private ListaClientes Clientes;
    
    /**
     * Constructor por defecto.
     * Se encarga de crear la lista de mensajes en espera vacía.
     */
    public MailServer() {
        Clientes=new ListaClientes();
        Mensajes=new ListaMensajes();
    }
    
    /**
     * Funcion que se encarga de retornar la cantidad de mensajes que un usuario ha recibido
     * como destinatario.
     * @param usuario nombre del cliente destinatario.
     * @return cantidad - cantidad de mensajes recibidos.
     */
    public int getMessagesWaiting(String usuario){
        int cantidad=0;
        int indice=0;
        while ((validarCliente(usuario))&&(indice<Mensajes.getCantidadElementos())){
            cantidad=cantidad+compararDestinatario(Mensajes.getMensaje(indice),usuario);
            indice++;
        }
        return cantidad;
    }
    
    /**
     * Funcion que se encarga de retornar el primer mensaje no leido que ha recibido el 
     * usuario
     * @param usuario El nombre del usuario destinatario.
     * @return Mensaje - El primer mensaje no leido del usuario.
     */
    public Message getNextMessage(String usuario){
        int indice=0;
        Message mensaje=null;
        while ((validarCliente(usuario))&&(indice<Mensajes.getCantidadElementos())&&(mensaje==null)){
            mensaje=obtenerMensajeDestinado(Mensajes.getMensaje(indice), usuario);
            indice++;
        }
        mensaje.LeerMensaje();
        return mensaje;
    }
    
    /**
     * Metodo que se encarga de recibir el mensaje enviado por un cliente y almacenarlo en
     * la lista de mensajes en espera para luego ser remitido al destinatario.
     * @param mensaje El mensaje a ser enviado
     */
    public void post(Message mensaje){
        Mensajes.ponerEnEspera(mensaje);
    }
    
    /**
     * Funcion que se encarga comparar el si un usuario es el destinatario de
     * un mensaje determinado.
     * Funcion empleada por el metodo getNextMessage para obtener el siguiente mensaje.
     * @param mensaje El mensaje a comparar
     * @param usuario El nombre del usuario destinatario 
     * @return Mensaje - Mensaje destinado al usuario
     */
    private Message obtenerMensajeDestinado(Message mensaje, String usuario){
        String destinatario=mensaje.Obtener_Destinatorio();
        if (destinatario.equals(usuario)){
            return mensaje;
        }
        return null;
    }

    /**
     * funcion que se encarga de comparar el si un usuario es el destinatario de
     * un mensaje determinado.
     * Funcion empleada en el metodo getMessagesWaiting, eliminarMensaje y leerMensaje
     * para contar los mensajes recibidos.
     * @param mensaje El mensaje que se desea comparar
     * @param usuario  El nombre del usuario destinatario 
     * @return 1 - Si el mensaje corresponde al usuario.
     */
    private int compararDestinatario(Message mensaje, String usuario) {
        String destinatario=mensaje.Obtener_Destinatorio();
        if (destinatario.equals(usuario)){
            return 1;
        }
        return 0;
    }
    
    /**
     * Metodo que se encarga de guardar el contenido del servidor en un archivo externo
     * para ser accedido por mas clientes.
     * @param direccion La direccion del archivo donde se desea almacenar el servidor.
     */
    public void exportar(String direccion){
        try {
            File file=new File(direccion);
            file.createNewFile();
            FileOutputStream fileOut=new FileOutputStream(file);
            ObjectOutputStream salida = new ObjectOutputStream(fileOut);
            salida.writeObject(this);
            salida.close();
        } catch (IOException ex) {
            Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Metodo que se encarga de importar el contenido de un servidor desde un archivo externo
     * donde se haya almacenado previamente este contenido.
     * @param file La direccion del archivo a leer.
     */
    public void importar(String file) {
        try {
            FileInputStream fileIn=new FileInputStream(file);
            ObjectInputStream entrada=new ObjectInputStream(fileIn);
            MailServer ServerAuxiliar=(MailServer)entrada.readObject();
            entrada.close();
            this.Clientes=ServerAuxiliar.Clientes;
            this.Mensajes=ServerAuxiliar.Mensajes;
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(MailServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Metodo que se encarga de registrar un nuevo cliernte en el servidor.
     * @param cliente El nombre del cliente a registrar.
     */
    public void registrarCliente(String cliente){
        Clientes.registrar(cliente);
    }
    
    /**
     * Metodo que se encarga de eliminar el registro de un cliente en el servidor.
     * @param cliente El nombre del cliente al que se desea eliminar.
     */
    public void eliminarCliente(String cliente){
        Clientes.eliminar(cliente);
    }
    
    /**
     * Funcion que verifica si un usuario se encuentra registrado en el servidor.
     * @param cliente El nombre del cliente a verificar.
     * @return true - Si se encuantra registrado, false en caso contrario.
     */
    public boolean validarCliente(String cliente){
        return Clientes.validar(cliente);
    }
    
    /**
     * Metodo que permite eliminar un mensaje de la bandeja de entrada de un usuario.
     * @param usuario El nombre del usuario propietario de la bandeja de entrada.
     * @param posicion El numero de mensaje en orden de llegada a la bandeja de entrada. 
     */
    public void eliminarMensaje(String usuario, int posicion){
        int indice=0;
        Message mensaje=null;
        int NumeroMensaje=0;
        List<Message> allMessages=getAllMessages(usuario);
        while ((validarCliente(usuario))&&(indice<allMessages.size())&&(NumeroMensaje!=posicion)){
            mensaje=allMessages.get(indice);
            NumeroMensaje=NumeroMensaje+compararDestinatario(mensaje, usuario);
            indice++;
        }
        Mensajes.eliminarMensaje(mensaje);
    }
    
    /**
     * Metodo que permite marcar como Leido un nuevo mensaje recibido.
     * @param usuario El Nombre del usuario del que se leera el mensaje.
     * @param posicion El numero de mensaje no leido en orden de llegada a la bandeja de entrada del usuario. 
     */
    public void LeerMensaje(String usuario, int posicion){
        int indice=0;
        Message mensaje=null;
        int NumeroMensaje=0;
        List<Message> newMessages=getNewMessages(usuario);
        while ((validarCliente(usuario))&&(indice<newMessages.size())&&(NumeroMensaje!=posicion)){
            mensaje=newMessages.get(indice);
            NumeroMensaje=NumeroMensaje+compararDestinatario(mensaje, usuario);
            indice++;
        }
        mensaje.LeerMensaje();
    }
    
    
    /**
     * Funcion que retorna la lista de todos los mensajes, leidos y no leidos, recibidos por un cliente.
     * @param usuario El nombre del usuario destinatario.
     * @return allMessages - La lista de todos los mensajes recibidos.
     */
    public List<Message> getAllMessages(String usuario){
        List<Message> allMessages=new ArrayList<Message>();
        for (int indice=0;indice<Mensajes.getCantidadElementos();indice++){
            Message mensaje=Mensajes.getMensaje(indice);
            addMessagetoList(mensaje, usuario, allMessages);
        }
        return allMessages;
    }
    
    /**
     * Metodo que agrega un mensaje destinado a un usuario a una lista enviada.
     * Metodo empleado por la funcion getAllMessages para componer la lista de mensajes recibidos.
     * @param mensaje El mensaje a añadir a la lista.
     * @param usuario El nombre del usuario destinatario.
     * @param mensajes La lista dende se añadira el mensaje si esta destinado al usuario.
     */
    private void addMessagetoList(Message mensaje, String usuario, List<Message> mensajes){
        String destinatario=mensaje.Obtener_Destinatorio();
        if (destinatario.equals(usuario)){
            mensajes.add(mensaje);
        }
    }
    
    
    /**
     * Metodo que agrega un mensaje destinado a un usuario y enviado a por un usuario especifico a una lista enviada.
     * Metodo empleado por la funcion getMessagesSender para componer la lista de mensajes remitidos por un usario.
     * @param mensaje El mensaje a añadir a la lista.
     * @param Remitiente El nombre del usuario remitente.
     * @param usuario El nombre del usuario destinatario.
     * @param mensajes La lista dende se añadira el mensaje si esta destinado al usuario y fuen enviado por Remitente.
     */
    private void addMessageSender(Message mensaje,String Remitente,String usuario,List<Message> mensajes){
      String remitente=mensaje.Obtener_Remitente();
       String destinatario=mensaje.Obtener_Destinatorio();
       if(destinatario.equals(usuario)&&remitente.equals(Remitente)){
         mensajes.add(mensaje);
       }
    }
    
    /**
     * Funcion que retorna la lista de mensajes enviados al destinatario por un remitente especifico.
     * @param usuario El nombre del usuario destinatario.
     * @param remitente El nombre del remitente a buscar.
     * @return Messages - La lista de mensajes enviados por el Remitente especifico.
     */
    public List<Message> getMessagesSender(String usuario,String remitente){
      List<Message> Messages=new ArrayList<Message>();
      for(int indice=0;indice<Mensajes.getCantidadElementos();indice++){
         Message mensaje=Mensajes.getMensaje(indice);
         addMessageSender(mensaje, remitente, usuario, Messages);
      }
      return Messages;
    }
    
    /**
     *Funcion que retorna la lista de mensajes aun no leidos por el usuario destinatario. 
     * @param usuario El nombre del usuario destinatario.
     * @return newMessages - La lista de mensajes no leidos.
     */
    public List<Message> getNewMessages(String usuario){
        List<Message> allmessages=getAllMessages(usuario);
        List<Message> newMessages=new ArrayList<Message>();
        for (int indice=0;indice<allmessages.size();indice++){
            Message mensaje=allmessages.get(indice);
            filtrarLeidos(mensaje,newMessages);
        }
        return newMessages;
    }

    /**
     *Metodo que verifica si un mensaje no fue leido y lo añade a una lista enviada.
     * @param mensaje El nombre del usuario destinatario.
     * @param newMessages La lista donde se añadira el mensaje no leido.
     */
    private void filtrarLeidos(Message mensaje, List<Message> newMessages) {
        if (!mensaje.getLeido()){
            newMessages.add(mensaje);
        }
    }
    
}
